﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace YAPL.Language.Core.Types {
	/// <summary>
	/// Base class for all classes defined in YAPL (user-defined and library classes either).
	/// Class instances are stored in global object collection.
	/// </summary>
	public class YAPLClass : YAPLObject {
		public static Random _rnd = new Random();
		public readonly static string METACLASS_SUFFIX;
		public static readonly string DYNAMIC_CLASS_SUFFIX;
		static YAPLClass() {

			METACLASS_SUFFIX = "_meta_" + GetUniqueClassId();
			DYNAMIC_CLASS_SUFFIX = "_dyn_" + GetUniqueClassId();
		}
		protected readonly FunctionCollection _methods = new FunctionCollection();
		protected readonly string _name;
		protected YAPLClass(string name, string metaclass) : base(metaclass) {
			_name = name;
		}

		public static string GetUniqueClassId() {
			var buff = new byte[6];
			_rnd.NextBytes(buff);
			return Convert.ToBase64String(buff);
		}

		#region object factories
		public static YAPLClass CreateClass(string name) {
			return new YAPLClass(name, name+METACLASS_SUFFIX);
		}

		public static YAPLClass CreateClass(string name, string metaclass) {
			return new YAPLClass(name, metaclass);
		}

		public static YAPLClass CreateMetaclass(string name) {
			return new YAPLClass(name + METACLASS_SUFFIX, name + METACLASS_SUFFIX);
		}

		public YAPLObject Instantiate() {
			if (IsMetaclass())
				return new YAPLObject(GetClassNameFromMetaclass(_name));
			return new YAPLObject(_name);
		}
		#endregion

		public static string GetMetaclassNameForClass(string className) {
			return className + METACLASS_SUFFIX;
		}

		public static string GetClassNameFromMetaclass(string metaclassName) {
			return (metaclassName.Remove(metaclassName.Length - METACLASS_SUFFIX.Length, METACLASS_SUFFIX.Length));
		}

		public bool IsMetaclass() {
			return _name.EndsWith(METACLASS_SUFFIX);
		}

		public bool IsDynamicClass() {
			return _name.EndsWith(DYNAMIC_CLASS_SUFFIX);
		}

		public FunctionCollection Methods {
			get { return _methods; }
		}

		public string Name {
			get { return _name; }
		}
	}
}
